
//+------------------------------------------------------------------+
//|                 Murrey Maths auto-trading EA by SteveHopwood.mq4 |
//|                                  Copyright © 2010, Steve Hopwood |
//|                              http://www.hopwood3.freeserve.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, Steve Hopwood"
#property link      "http://www.hopwood3.freeserve.co.uk"
#include <WinUser32.mqh>
#include <stdlib.mqh>

#define  NL    "\n"
#define  upperhedgeline "mmlUpper hedge line"
#define  lowerhedgeline "mmlLower hedge line"
#define  gap  "                                "
#define  C      ","

//I have taken the code that displays the MM lines directly from this indicator.
//My grateful appreciation to the authour of the indi.
//+------------------------------------------------------------------+
//|                                           Murrey_Math_Line_X.mq4 |
//|                         Copyright © 2004, Vladislav Goshkov (VG).|
//|                                                      4vg@mail.ru |
//|                                 code change by Alex.Piech.FinGeR |
//+------------------------------------------------------------------+
/*
bool IsBarClosed(int timeframe,bool reset)
void LookForLimitOpportunities()
void del_obj(string UniqueID)  
string FindLastVLine()
void GetLinesFromGV()
void DrawLines()
double GetRange(string HiLo, int period) 
bool CheckOutsideSession( int StartHour, int EndHour, int ct)
bool CheckTradeFilters()
bool CheckTradingTimes()
void GetCurrentMMlPosition()
bool DoesTradeExist(double lot)
bool IsThisPairTradable()
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
void CountOpenTrades()
void TradeDirectionBySwap()
bool ShouldWinningPositionClose()
void LookForPendingDeletion()
void DeletePendingTrades()
void CloseAllTrades()
void MaintainGVs()
----Deal with losing trades
void HasMarketPassedExtreme()
bool HedgePosition()
void LookForFailedHedging()

*/

extern string  gi                      = "----General inputs----";
extern double  Lot1                    = 0.01;
extern double  Lot2                    = 0.01;
extern double  Lot3                    = 0.01;
extern double  Lot4                    = 0.01;    

extern string  tr                      = "----Trading----";
extern bool    TradeLong               = true;
extern bool    TradeShort              = true;
extern bool    UseLimitOrders          = false;
extern bool    UseStopOrders           = true;

extern double  MinBandSizeForTrading   = 0;	      //Minimum distance between MML's for opening trades

extern int     MaxTrades               = 3;           //Maximum recovery iterations eg 3= 1.2.6, 2=1.2
extern int     FirstTradeLine          = 3;           //0,1,2 or 3.The MML at which Lot1 trades are taken. Use in conjunction with MaxTrades
extern bool    CriminalIsECN           = false;       


/////////////////////////////////////////////////////////////////////////////
//    Murrey Math Externs
/////////////////////////////////////////////////////////////////////////////
extern string     UniqueID                      = "MEDS_MML";
extern bool       UseOriginalCalcs              = false;              //Set True to use VG MML calculation
extern bool       UseFractalMultiplier          = true;              //Use multiplier to ensure fractal is ALWAYS 10000
extern bool       UseCloseForRangeCalcs         = false;              //Original Murrey rules do not use wicks to calculate ranges
extern int        P                             = 118;               
extern int        MMPeriod                      = 0;                 //Use current timeframe
extern int        NumBars                       = 800;



//string         UniqueID                = "MEDS_MML";  //Must be the same as the prefix of the lines drawn by the mml indy
extern int     MagicNumber             = 0;
extern bool    VisibleTP               = false;       //Send TP with order
extern bool    VisibleSL               = false;       //Set a stoploss trades

extern string  tp                      = "----Take Basket Profits----";
extern bool    TakeProfitBasket        = false;       // If the basket hits the defined profit level then close all trades for this pair
extern int     TakeProfitPercentage    = 0;           // Zero means do not use this.Close basket based on percentage of account balance.
extern int     TakeProfitDollar        = 0;           // Zero means do not use this.Close basket based on hard dollar value
extern double  TargetAsPercentofOctave = 300;         // Percentage of MML for TP.
extern double  StopAsPercentofOctave   = 0;           // Percentage of MML for SL.

extern string  bf                      = "----Trading balance filters----";
extern bool    UseZeljko               = false;
extern bool    OnlyTradeCurrencyTwice  = false;

extern string  lto                     = "----Death trade options----";
extern bool    CloseLosingBasket       = true;

extern string  hed                     = "Hedging";
extern bool    UseHedging              = false;
extern double  HedgeLotMultiplier      = 1;
extern double  MMLSToHedgeLine         = 0;           //Distance from outer yellow lines to hedge line -ve means inside hedgeline
extern bool    CloseHedgeOnReturnToGrid= false;

extern bool    SaveLinesWhenTradesOpen = false;       //Set to true if you do not want the lines to redraw when trades are live

bool    ChngMNOnRedraw          = false;       //Change the Magic number when lines redraw so trades can be isolated
                                                      //NB.1 Current open trades will no longer be managed by Pippo
                                                      //NB.2 This setting is NOT compatible with SaveLinesWhenTradesOpen
bool    TakeProfitOnRedraw      = true;        //Take basket profit if lines redraw when trade is in profit
bool    TakeProfitOnRangeTouch  = true;        //Take basket profit if price hits the white range line before TP

extern string  sm0                     = "--Trading Hours Filter--";
extern string  sm1                     = " Times are GMT when UseDST=false";
extern string  sm2                     = "UseTradingHours - Enter 0 for false, 1 for true";
extern int     UseTradingHours         = 1;
extern string  sm4                     = "TradeAsian - Enter 0 for false, 1 for true";
extern int     TradeAsianMarket        = 1;
extern int     AsianStart              = 0100;       // Start trades after time
extern int     AsianStop               = 0700;      // Stop trading after time
extern string  sm5                     = "Trade Europe - Enter 0 for false, 1 for true";
extern int     TradeEuropeanMarket     = 1;
extern int     EurStart                = 0700;       // Start trades after time
extern int     EurStop                 = 1400;      // Stop trading after time
extern string  sm6                     = "Trade NY - Enter 0 for false, 1 for true";
extern int     TradeNewYorkMarket      = 1;
extern int     NYStart                 = 1400;       // Start trades after time
extern int     NYStop                  = 2100;       // Stop trading after time




extern string  amc                     = "----Available Margin checks----";
extern string  sco                     = "Scoobs";
extern bool    UseScoobsMarginCheck    = false;
extern string  fk                      = "ForexKiwi";
extern bool    UseForexKiwi            = false;
extern int     FkMinimumMarginPercent  = 1100;

extern string  pts                     = "----Swap filter----";
extern bool    CadPairsPositiveOnly    = false;
extern bool    AudPairsPositiveOnly    = false;
extern bool    NzdPairsPositiveOnly    = false;

extern string  ot                      = "----Other----";
extern bool    RemoveArrowsOnExit      = false;       
extern bool    Debug                   = false;       //Debug  logging on/off
extern bool    Error                   = false;       //error  logging on/off
extern bool    Timing                  = false;       //Timing logging on/off


extern color      clr_m_2_8 = Yellow;         extern int    wdth_m_2_8 = 2;		//  [-2]/8
extern color      clr_m_1_8 = HotPink;        extern int    wdth_m_1_8 = 2;		//  [-1]/8
extern color      clr_0_8   = DeepSkyBlue;    extern int    wdth_0_8   = 2;		//  [0]/8 
extern color      clr_1_8   = DarkOrange;     extern int    wdth_1_8   = 2;		//  [1]/8 
extern color      clr_2_8   = Red;            extern int    wdth_2_8   = 1;		//  [2]/8 
extern color      clr_3_8   = Green;          extern int    wdth_3_8   = 1;		//  [3]/8 
extern color      clr_4_8   = Blue;           extern int    wdth_4_8   = 2;		//  [4]/8 
extern color      clr_5_8   = Green;          extern int    wdth_5_8   = 1;		//  [5]/8 
extern color      clr_6_8   = Red;            extern int    wdth_6_8   = 1;		//  [6]/8 
extern color      clr_7_8   = DarkOrange;     extern int    wdth_7_8   = 2;		//  [7]/8 
extern color      clr_8_8   = DeepSkyBlue;    extern int    wdth_8_8   = 2;		//  [8]/8 
extern color      clr_p_1_8 = HotPink;        extern int    wdth_p_1_8 = 2;		//  [+1]/8
extern color      clr_p_2_8 = Yellow;         extern int    wdth_p_2_8 = 2;		//  [+2]/8
/////////////////////////////////////////////////////////////////////////////
//    Murrey Math Variables
/////////////////////////////////////////////////////////////////////////////
bool    fractalDone = false;
bool    Redraw;
double  buffer1[], buffer2[];
double  MMmultiplier;
double  dmml = 0, dvtl = 0,
        sum  = 0,
        v1 = 0,  v2 = 0,
        mn = 0,  mx = 0, mmx,
        mml[13], x[7], y[7], 
        octave = 0, fractal = 0, range   = 0,
        finalH  = -100000000, finalL  = 999999999;
string  ln_txt[13],  buff_str = "",  buff_str1 = "",buff_str2 = "",RedrawDate;
int     bn_Lo   = -1, bn_Hi   = -1, bn_v1   = 0, bn_v2   = 0,
        OctLinesCnt = 13,
        clr[13], wdth[13], shft = 0,
        nTime = 0, CurPeriod = 0, nDigits = 0;
int 	  NewPeriod=0;

   
double  lastMML,lastOctave,lastfinalH ,lastfinalL,lastDmml;
double     SetOctave                     = 0;                 //Do not use
int        OctaveMultiplier              = 0;                 //Do not use
string description = "", text = "";



//Lines variables
double         BandHigh, 
               BandLow;//Hi-lo of the market's MM Band
string         name;


//Trading Variables
int            Band,
               OpenTrades,
               PendingTrades,
               Filled, 
               TradeTicketNo[5];//Will use 1 to 4
bool           BuyOpen, 
               SellOpen,
               BuyPending, 
               SellPending,//Set to true if pendings are in place
               ForceTradeClosure, 
               ForcePendingTradeDeletion;
double         stoplevel,            
               aLot[5];          

//Hedging
bool           HedgingInProgress;
double         OpenLots,
               BasketUpl;

//Globals
string         gvBase;
bool           GetGVs;

//Matt's O-R stuff
int 	         O_R_Setting_max_retries 	= 1000;
double 	      O_R_Setting_sleep_time 		= 4.0; /* seconds */
double 	      O_R_Setting_sleep_max 		= 15.0; /* seconds */

//Miscellaneous
double         multiplier;
datetime       LastRunTime;
double         uHedgeLine, lHedgeLine;
bool           YesStop;


string         ScreenMessage,
               TradeComment;       
int            i = 0;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
{
   del_obj(UniqueID);
   
   string FunctionName = "init";
	int start = GetTickCount();
//---- Do the multiplier for 3 and 5 digit crims
  	double multiplier;
   if(Digits == 2 || Digits == 4) multiplier = 1;
   if(Digits == 3 || Digits == 5) multiplier = 10;
   if(Digits == 6) multiplier = 100;   
   if(Digits == 7) multiplier = 1000;   

   MinBandSizeForTrading  *=  multiplier;

//---- Set the base text for Globals
   gvBase = Symbol()+ Period() + MagicNumber + "_";

//---- Set MinBandSizeForTrading
   MinBandSizeForTrading = NormalizeDouble(MinBandSizeForTrading * Point, Digits);

//---- Set Var to get MML's from Globals on first Tick
   GetGVs = true;
   if (!SaveLinesWhenTradesOpen) DeleteGlobals();
//-- Get Stop level
   stoplevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;

//---- Set Base Trade Comment
   TradeComment = MagicNumber;

//---- Set Lot Values
   aLot[1]    = Lot1;
   aLot[2]    = Lot2;
   aLot[3]    = Lot3;
   aLot[4]    = Lot4;

//---- Set MurreyMath Timeframe
   if(MMPeriod>0 )   {//		Set  a period appropriate to the timeframe//
      NewPeriod   = P*MathCeil(MMPeriod/Period());   
   }  
   else    { 
      NewPeriod = P; 
   }

//---- Set Murrey Math Formats
   clr[0]  = clr_m_2_8;   wdth[0] = wdth_m_2_8; ln_txt[0]  = "                              [-2/8]Extreme";// "extreme              
   clr[1]  = clr_m_1_8;   wdth[1] = wdth_m_1_8; ln_txt[1]  = "                              [-1/8]Overshoot";// "overshoot          
   clr[2]  = clr_0_8;     wdth[2] = wdth_0_8;   ln_txt[2]  = "                              [0/8]Ultimate";// "Ultimate             
   clr[3]  = clr_1_8;     wdth[3] = wdth_1_8;   ln_txt[3]  = "                              [1/8]Weak";// "Weak, Stall and Reverse  
   clr[4]  = clr_2_8;     wdth[4] = wdth_2_8;   ln_txt[4]  = "                              [2/8]Major";// "Pivot, Reverse - major  
   clr[5]  = clr_3_8;     wdth[5] = wdth_3_8;   ln_txt[5]  = "                              [3/8]Top";// "Bottom of Trading Range   
   clr[6]  = clr_4_8;     wdth[6] = wdth_4_8;   ln_txt[6]  = "                              [4/8]Pivot";// "Major S/R Pivotal Point 
   clr[7]  = clr_5_8;     wdth[7] = wdth_5_8;   ln_txt[7]  = "                              [5/8]Bottom";// "Top of Trading Range   
   clr[8]  = clr_6_8;     wdth[8] = wdth_6_8;   ln_txt[8]  = "                              [6/8]Major";// "Pivot, Reverse - major  
   clr[9]  = clr_7_8;     wdth[9] = wdth_7_8;   ln_txt[9]  = "                              [7/8]Weak";// "Weak, Stall and Reverse  
   clr[10] = clr_8_8;     wdth[10]= wdth_8_8;   ln_txt[10] = "                              [8/8]Ultimate";// "Ultimate             
   clr[11] = clr_p_1_8;   wdth[11]= wdth_p_1_8; ln_txt[11] = "                              [+1/8]Overshoot";// "overshoot          
   clr[12] = clr_p_2_8;   wdth[12]= wdth_p_2_8; ln_txt[12] = "                              [+2/8]Extreme";// "extremely overshoot  
   
//---- Set Murrey Math multiplier
   if (!UseOriginalCalcs)  {MMmultiplier = MathPow(10,Digits -1);}//murrey math works on pip values
   else  {MMmultiplier = 1;}
   Comment(" "); 
   
   CalculateMMLs(true);

//---- Get time of Current Bar
   LastRunTime = iTime(NULL,0,0);
//----
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
   return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
{
//----
   string FunctionName = "deinit";
   int start = GetTickCount( );
   Comment(" ");   
   if(RemoveArrowsOnExit )del_obj("#");
   del_obj(UniqueID);
   return(0);
}
//+------------------------------------------------------------------+
//| del_obj(string key)                                              |
//+------------------------------------------------------------------+
void del_obj(string key)  
{
   string FunctionName = "del_obj";
   int start = GetTickCount( );
   int k=0;
   while (k<ObjectsTotal())   
   {
      string objname = ObjectName(k);
      if (StringSubstr(objname,0,StringLen(key)) == key)
      { 
         ObjectDelete(objname);
      }
      else
      {
         k++;
      }
   }//while (k<ObjectsTotal())      
   return(0);
}
//+------------------------------------------------------------------+
string FindLastVLine()  
{
   string FunctionName = "FindLastVLine";
   int start = GetTickCount( );
   int k=0;
   datetime dt = 0;
   while (k<ObjectsTotal())   
   {
      string objname = ObjectName(k);
    
      if (StringSubstr(objname,0,StringLen(UniqueID + " Redraw")) == UniqueID + " Redraw")
      { 
         if (dt < ObjectGet(objname , OBJPROP_TIME1))
         {
            dt = ObjectGet(objname , OBJPROP_TIME1);
         }
      }
      k++;
   }//while (k<ObjectsTotal())      
   if(Debug)Print(FunctionName,C," LastVline=", TimeToStr(dt,TIME_DATE|TIME_MINUTES));

   return(TimeToStr(dt));
}  
//+------------------------------------------------------------------+
void GetLinesFromGV()
{
   string FunctionName = "GetLinesFromGV";
   for( i=0; i<OctLinesCnt; i++ )
   {
      mml[i] = gvg( "mml" + i);
      if(Debug)Print(FunctionName,C, "INIT2:-mml[",i,"]=",mml[i]);
   }//for( i=0; i<OctLinesCnt; i++ )

   dmml = mml[1]-mml[0];

   uHedgeLine =  gvg(upperhedgeline);
   lHedgeLine =  gvg(lowerhedgeline);       

   DrawHedgeLines();
   
}//GetLinesFromGV()
//+------------------------------------------------------------------+
//| DrawLines()                           |
//+------------------------------------------------------------------+
void DrawLines()
{   
   string FunctionName = "DrawLines";
   int start = GetTickCount( );
   if (Debug) Print( "Starting Drawlines"); 
   
   name = FindLastVLine();   

   if(Debug)Print( FunctionName,C," LastVline=",name);
   for( i=0; i<OctLinesCnt; i++ )
   {
      string objname ="";
      objname = UniqueID + i + "-" + name;
      mml[i] = ObjectGet(objname,OBJPROP_PRICE1);
      if(Debug)Print( FunctionName,C,"mml[",i,"]=",mml[i]);
   }

   dmml = mml[1]-mml[0];
      
   uHedgeLine = NormalizeDouble(mml[12] + (dmml * MMLSToHedgeLine), Digits);
   lHedgeLine = NormalizeDouble(mml[ 0] - (dmml * MMLSToHedgeLine), Digits);
      
   DrawHedgeLines();

}//End void DrawLines()

//+---------------------------------------------------------------------
void DrawHedgeLines()
{
   string FunctionName = "DrawHedgeLines";
   int start = GetTickCount( );
   if(ObjectFind(upperhedgeline) == -1 )
   {
      ObjectCreate(upperhedgeline, OBJ_HLINE , 0,Time[0], uHedgeLine);
      ObjectSet(upperhedgeline, OBJPROP_STYLE, STYLE_DOT);
      ObjectSet(upperhedgeline, OBJPROP_COLOR, Red);
      ObjectSet(upperhedgeline, OBJPROP_WIDTH, 0);
   }//if(ObjectFind(upperhedgeline) == -1 )
   else
   {
      ObjectMove(upperhedgeline,0,Time[0],uHedgeLine); 
   } //else  
   if(ObjectFind(lowerhedgeline) == -1 )
   {
      ObjectCreate(lowerhedgeline, OBJ_HLINE , 0,Time[0], lHedgeLine);
      ObjectSet(lowerhedgeline, OBJPROP_STYLE, STYLE_DOT);
      ObjectSet(lowerhedgeline, OBJPROP_COLOR, Red);
      ObjectSet(lowerhedgeline, OBJPROP_WIDTH, 0);
   }//if(ObjectFind(lowerhedgeline) == -1 )
   else
   {
      ObjectMove(lowerhedgeline,0,Time[0], lHedgeLine); 
   }//else   

   if(Debug)Print(FunctionName,C,upperhedgeline,C,uHedgeLine,C,"Time=",TimeToStr(Time[0]));
   if(Debug)Print(FunctionName,C,lowerhedgeline,C,lHedgeLine,C,"Time=",TimeToStr(Time[0]));
   
}//void DrawHedgeLines()
//-------------------------------------------------------------------+
double      RangeHigh,
            RangeLow,
            RangeDiff;// measured in MML's
bool        TouchRangeHigh,
            TouchRangeLow;
extern int  RangePeriod       = 192;
               

//+------------------------------------------------------------------+
void GetRange1()  
{
   //Call with RangePeriod value
   int  Lo,Hi;  
if(Debug)Print("HERE");
   Lo = iLowest(NULL,0,MODE_LOW,RangePeriod,0);
   Hi = iHighest(NULL,0,MODE_HIGH,RangePeriod,0);
   RangeLow  = Low [Lo];
   RangeHigh = High[Hi];	   
//   RangeDiff = (RangeHigh - RangeLow)/ dmml;
   
   for (int f = 1920;f>=0;f--)
   {
if(Debug)Print("Ziggy ",f,"= ",iCustom(NULL,0,"ZigZag",12,5,3,0,f));
   }
   
   
if(Debug)Print(" bn_Hi =", Hi,",bn_Lo =", Lo ,",RangeLow=",RangeLow,",RangeHigh=",RangeHigh,",RangePeriod=",RangePeriod);

   return;
      
}//double GetRange(string HiLo, int period)	   

//+---------------------------------------------------------------------------------------
bool CheckTradeFilters()
{
   bool myStop, Expired;
   double CurrentSpread;
   
   myStop = false;
      
   if (myStop ==false)
   {
   if (UseTradingHours == 1)
   {
     myStop = CheckTradingTimes();
   
   }
   }
     
   
   return(myStop);
}

// Return true if time is not in session for trading
bool CheckOutsideSession( int StartHour, int EndHour, int ct)
{
  if(StartHour<=EndHour)
  {
    if(ct < StartHour || ct > EndHour) return(true) ;
  }
  else
  {
    if(ct > EndHour && ct < StartHour) return(true) ;
  }
  return(false) ;
}

bool CheckTradingTimes()
{
   bool StopTrading;
   int ct;
   ct = Hour() * 100 + Minute();
   
     StopTrading = true;
// Check trading Asian Market
     if (TradeAsianMarket == 1)
     {
        StopTrading = CheckOutsideSession(AsianStart, AsianStop, ct);
     }
     if (StopTrading == true)
     {
// Check trading European Market
       if (TradeEuropeanMarket == 1)
       {
         StopTrading = CheckOutsideSession(EurStart, EurStop, ct);
       }
     }
     if (StopTrading == true)
     {
// Check trading New York Market
       if (TradeNewYorkMarket == 1)
       {
         StopTrading = CheckOutsideSession(NYStart, NYStop, ct);
       }
     }
     
     return(StopTrading);
}//+------------------------------------------------------------------+
void GetCurrentMMlPosition()
{   
   string FunctionName = "GetCurrentMMlPosition";
   int start = GetTickCount( );
   BandHigh = -1;
   BandLow = -1;
   Band = 1;
      
   //Calculates the hi-lo of the current band

   if(Bid < mml[0] || Bid > mml[12]) Band=-1;//Price is outside Yellow

   for (int cc = 0; cc <= OctLinesCnt-1; cc++)
   {  
      if (Bid >= mml[cc] && Bid <= mml[cc + 1] )
      {
         BandHigh = mml[cc + 1];
         BandLow = mml[cc];
         break;
      }//if (Bid >= mml[cc] && Bid <= mml[cc + 1] )
      Band++;
   }//for (int cc = 0; cc <= OctLinesCnt-1; cc++)

}//void GetCurrentMMlPosition()

//+---------------------------------------------------------------------
bool DoesTradeExist(int AboveBelow, double price)
{
   string FunctionName = "DoesTradeExist";
   int start = GetTickCount( );
   //-1 = below for longtrades  1= above for shorttrades
      
   if (OrdersTotal() == 0) return(false);
   
   for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderCloseTime() > 0) continue;
      if (OrderSymbol() != Symbol() ) continue;

      if (AboveBelow > 0 && OrderOpenPrice() > price) return(true);
      if (AboveBelow < 0 && OrderOpenPrice() < price) return(true);   
   }//for (int cc = 0; cc <= OrdersTotal() - 1; cc++)
   
   return(false);
   
}//bool DoesTradeExist(double lot)

//+-------------------------------------------------------------------------------------
void DeletePendingTrades()
{
   string FunctionName = "DeletePendingTrades";
   int start = GetTickCount( );
   ForcePendingTradeDeletion = false;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderSymbol() != Symbol() ) continue;

      int tn = OrderTicket();
      while(IsTradeContextBusy()) Sleep(100);
      if (( OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT 
         || OrderType() == OP_BUYSTOP  || OrderType() == OP_SELLSTOP ) && OrderCloseTime() == 0) 
      {
         if(Debug)Print("About to delete pendings");
         bool result = OrderDelete(tn);      
         if (result) cc++;

         if (!result) ForcePendingTradeDeletion = true;//Force a retry at the next tick
      }//if (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT) 
      
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

}//End void DeletePendingTrades()

//+---------------------------------------------------------------------------------

double take, stop, price, lotsize;
int type, LastTradeLine;
double trigger;
bool Send;

//+---------------------------------------------------------------------------------
int LookForStopOpportunities()
{
   int start = GetTickCount( );
   if (Band > FirstTradeLine && Band < (12 - FirstTradeLine + 1)) return;

   //Balance filter
   if (UseZeljko && !BalancedPair(OP_BUY)   && Filled  == 0) return;
   if (UseZeljko && !BalancedPair(OP_SELL)  && Filled == 0) return;

   //Only trade a currency twice
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      if (!IsThisPairTradable() ) return;
   }//if (OnlyTradeCurrencyTwice)

   int TotalTrades = PendingTrades + OpenTrades;

   Send = false;
   take= 0; stop =0; price = 0;
   double LastClose = iClose(NULL,0,1);
   double LastOpen  = iOpen (NULL,0,1);
   double ThisOpen  = iOpen (NULL,0,0);
   double LastLow   = iLow  (NULL,0,1);
   
   int temp;

   string FunctionName = "TradingOpportunities";   
   //Long opportunities 
   temp = FirstTradeLine;
   LastTradeLine = temp - MaxTrades +1; 
   
   for (int m = temp; m>=LastTradeLine; m--)
   {
      trigger = NormalizeDouble(mml[m], Digits);
      if(Debug)Print(FunctionName
                     ,C,"m=",m
                     ,C,"trigger=",trigger
                     ,C,"Bid=", Bid
                     ,C,"trigger=",trigger
                     ,C,"trigger+stoplevel=",trigger+stoplevel
                     ,C,"trigger +  dmml*0.5=",trigger +  dmml*0.5
                     ,C,"PendingTrades=",PendingTrades
                     ,C,"aLot[TotalTrades+1]=",aLot[TotalTrades+1]
                     );

      if (TradeLong && Band == m && Bid < trigger - stoplevel && Bid > MathMin(trigger - stoplevel,trigger - dmml*0.5) && !DoesTradeExist(1, Bid))
      {
         if(VisibleTP) take = NormalizeDouble(trigger + (dmml * TargetAsPercentofOctave /100 ), Digits);
         if(VisibleSL) stop = NormalizeDouble(trigger - (dmml * StopAsPercentofOctave   /100 ), Digits); // Paul addition for Sandovichtype = OP_BUYLIMIT;
         if(Debug)Print("long opportunity3:trigger=",trigger );
         type = OP_BUYSTOP;
         price = trigger;
         Send = true;
         lotsize = aLot[TotalTrades+1];
         TradeComment = MagicNumber + "_BS";
         return(1);         
      }
   }
   //short opportunities
   temp = 12 - FirstTradeLine ;
   LastTradeLine = temp + MaxTrades - 1; 

   for ( m = temp; m<=LastTradeLine; m++)
   {
      trigger = NormalizeDouble(mml[m], Digits);
      if(Debug)Print(FunctionName
                     ,C,"m=",m
                     ,C,"trigger=",trigger
                     ,C,"Bid=", Bid
                     ,C,"trigger=",trigger
                     ,C,"trigger-stoplevel=",trigger-stoplevel
                     ,C,"trigger -  dmml*0.5=",trigger-dmml*0.5
                     ,C,"PendingTrades=",PendingTrades
                     ,C,"aLot[TotalTrades+1]=",aLot[TotalTrades+1]
                     );
      if (TradeShort && Band == m + 1  && Bid > trigger + stoplevel && Bid < MathMax(trigger + stoplevel,trigger +  dmml*0.5) && !DoesTradeExist(-1, Bid))
      {
         if(VisibleTP) take = NormalizeDouble(trigger - (dmml *TargetAsPercentofOctave /100), Digits);
         if (VisibleSL) stop = NormalizeDouble(trigger + (dmml * StopAsPercentofOctave /100 ), Digits);
         if (Debug)Print("short opportunity3:trigger=",trigger );
         type = OP_SELLSTOP;
         price = trigger;
         Send = true;
         lotsize = aLot[TotalTrades+1];
         TradeComment = MagicNumber + "_SS";
         return(-1); 
      }
   }  

   return(0);   
}//LookForStopOpportunities()
//+---------------------------------------------------------------------------------
int LookForLimitOpportunities()
{  
   int start = GetTickCount( );
if (Band > FirstTradeLine +1  && Band < (12 - FirstTradeLine -1)) return;

   //Balance filter
   if (UseZeljko && !BalancedPair(OP_BUY)   && Filled  == 0) return;
   if (UseZeljko && !BalancedPair(OP_SELL)  && Filled == 0) return;

   //Only trade a currency twice
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      if (!IsThisPairTradable() ) return;
   }//if (OnlyTradeCurrencyTwice)

   int TotalTrades = PendingTrades + OpenTrades;

   Send = false;
   take= 0; stop =0; price = 0;
   //double target;
   int temp;
   string FunctionName = "TradingOpportunities";   
   //Long opportunities 
   temp = FirstTradeLine;
   LastTradeLine = temp - MaxTrades +1; 
   
   for (int m = temp; m>=LastTradeLine; m--)
   {
      trigger = NormalizeDouble(mml[m], Digits);
      if(Debug)Print(FunctionName
                     ,C,"m=",m
                     ,C,"trigger=",trigger
                     ,C,"Bid=", Bid
                     ,C,"trigger=",trigger
                     ,C,"trigger+stoplevel=",trigger+stoplevel
                     ,C,"trigger +  dmml*0.5=",trigger +  dmml*0.5
                     ,C,"PendingTrades=",PendingTrades
                     ,C,"aLot[TotalTrades+1]=",aLot[TotalTrades+1]
                     );

      if (TradeLong && (Bid > (trigger + stoplevel ) && Bid < MathMax((trigger + stoplevel ),(trigger +  dmml*0.5)))  && !DoesTradeExist(-1, Bid))
      {
         if(VisibleTP) take = NormalizeDouble(trigger + (dmml * TargetAsPercentofOctave /100 ), Digits);
         if(VisibleSL) stop = NormalizeDouble(trigger - (dmml * StopAsPercentofOctave   /100 ), Digits); // Paul addition for Sandovichtype = OP_BUYLIMIT;
         if(Debug)Print("long opportunity3:trigger=",trigger );
         type = OP_BUYLIMIT;
         price = trigger;
         Send = true;
         lotsize = aLot[TotalTrades+1];
         TradeComment = MagicNumber + "_BL";
         return(1);         
      }
   }
   //short opportunities
   temp = 12 - FirstTradeLine ;
   LastTradeLine = temp + MaxTrades - 1; 

   for ( m = temp; m<=LastTradeLine; m++)
   {
      trigger = NormalizeDouble(mml[m], Digits);
      if(Debug)Print(FunctionName
                     ,C,"m=",m
                     ,C,"trigger=",trigger
                     ,C,"Bid=", Bid
                     ,C,"trigger=",trigger
                     ,C,"trigger-stoplevel=",trigger-stoplevel
                     ,C,"trigger -  dmml*0.5=",trigger-dmml*0.5
                     ,C,"PendingTrades=",PendingTrades
                     ,C,"aLot[TotalTrades+1]=",aLot[TotalTrades+1]
                     );
      if (TradeShort && (Bid < (trigger - stoplevel)  && Bid > MathMin((trigger - stoplevel ),(trigger -  dmml*0.5)))  && !DoesTradeExist(1, Bid))
      {
         if(VisibleTP) take = NormalizeDouble(trigger - (dmml *TargetAsPercentofOctave /100), Digits);
         if (VisibleSL) stop = NormalizeDouble(trigger + (dmml * StopAsPercentofOctave /100 ), Digits);
         if (Debug)Print("short opportunity3:trigger=",trigger );
         type = OP_SELLLIMIT;
         price = trigger;
         Send = true;
         lotsize = aLot[TotalTrades+1];
         TradeComment = MagicNumber + "_SL";
         return(-1); 
      }
   }  

   return(0);
}//int LookForLimitOpportunities()

//+---------------------------------------------------------------------------------
void SendTrade(int type, double price, double lotsize,double take,double stop)
{
   string FunctionName = "SendTrade";
   int start = GetTickCount( );

   //Neutralise the tp if necessary   
   bool result = SendSingleTrade(type, TradeComment, lotsize, price, stop, take);
   // else result = SendSingleTrade(type, TradeComment, lotsize, price, 0, take);      
   int TicketNo;

   if (result) 
   {
      OrderSelect(TicketNo, SELECT_BY_TICKET);
      if (type == OP_BUYLIMIT || type == OP_BUYSTOP)
      {
         if (OrderLots() == aLot[1] && TradeTicketNo[1] == -1 ) TradeTicketNo[1] = TicketNo; return;
         if (OrderLots() == aLot[2] && TradeTicketNo[2] == -1 ) TradeTicketNo[2] = TicketNo; return;
         if (OrderLots() == aLot[3] && TradeTicketNo[3] == -1 ) TradeTicketNo[3] = TicketNo; return;
         if (OrderLots() == aLot[4] && TradeTicketNo[4] == -1 ) TradeTicketNo[4] = TicketNo;  return;       
      }//if (type == OP_BUYLIMIT)
         
      if (type == OP_SELLLIMIT || type == OP_SELLSTOP)
      {
         if (OrderLots() == aLot[1] && TradeTicketNo[1] == -1 ) TradeTicketNo[1] = TicketNo; return;
         if (OrderLots() == aLot[2] && TradeTicketNo[2] == -1 ) TradeTicketNo[2] = TicketNo; return;
         if (OrderLots() == aLot[3] && TradeTicketNo[3] == -1 ) TradeTicketNo[3] = TicketNo; return;
         if (OrderLots() == aLot[4] && TradeTicketNo[4] == -1 ) TradeTicketNo[4] = TicketNo; return;        
      }//if (type == OP_SELLLIMIT)

         
   }//if (result) 
      
}//void SendTrade()

//+---------------------------------------------------------------------------------
bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)
{
   
   string FunctionName = "SendSingleTrade";
   int start = GetTickCount( );

   int slippage = 10;
   int err;
   if (Digits == 3 || Digits == 5) slippage = 100;
   
   color col = Red;
   if (type == OP_BUY || type == OP_BUYLIMIT) col = Green;
   
   int expiry = 0;
   //if (SendPendingTrades) expiry = TimeCurrent() + (PendingExpiryMinutes * 60);

   if (!CriminalIsECN) int ticket = OrderSend(Symbol(),type, lotsize, price, slippage, stop, take, comment, MagicNumber, expiry, col);

   //Is a 2 stage criminal
   if (CriminalIsECN)
   {
      bool result;
      
      ticket = OrderSend(Symbol(),type, lotsize, price, slippage, 0, 0, comment, MagicNumber, expiry, col);
      if (ticket > 0)
      {
         if (take > 0 && stop > 0)
         {
            while(IsTradeContextBusy()) Sleep(100);
            result = OrderModify(ticket, OrderOpenPrice(), stop, take, OrderExpiration(), CLR_NONE);
            if (!result)
            {
               err=GetLastError();
               if(Error)Print(Symbol(), " SL/TP  order modify failed with error(",err,"): ",ErrorDescription(err));               
            }//if (!result)			  
         }//if (take > 0 && stop > 0)
      
         if (take != 0 && stop == 0)
         {
            while(IsTradeContextBusy()) Sleep(100);
            result = OrderModify(ticket, OrderOpenPrice(), OrderStopLoss(), take, OrderExpiration(), CLR_NONE);
            if (!result)
            {
               err=GetLastError();
               if(Error)Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
            }//if (!result)			  
         }//if (take == 0 && stop != 0)

         if (take == 0 && stop != 0)
         {
            while(IsTradeContextBusy()) Sleep(100);
            result = OrderModify(ticket, OrderOpenPrice(), stop, OrderTakeProfit(), OrderExpiration(), CLR_NONE);
            if (!result)
            {
               err=GetLastError();
               if(Error)Print(Symbol(), " SL  order modify failed with error(",err,"): ",ErrorDescription(err));               
            }//if (!result)			  
         }//if (take == 0 && stop != 0)

      }//if (ticket > 0)

   }//if (CriminalIsECN)

   //Error trapping for both
   if (ticket < 0)
   {
      string stype;
      if (type == OP_BUY) stype = "OP_BUY";
      if (type == OP_SELL) stype = "OP_SELL";
      if (type == OP_BUYLIMIT) stype = "OP_BUYLIMIT";
      if (type == OP_SELLLIMIT) stype = "OP_SELLLIMIT";
      if (type == OP_BUYSTOP) stype = "OP_BUYSTOP";
      if (type == OP_SELLSTOP) stype = "OP_SELLSTOP";
      err=GetLastError();
      
      if(Error)Print(Symbol(), " ", stype," order send failed with error(",err,"): ",ErrorDescription(err));
      return(false);
   }//if (ticket < 0)  
   
   
   int TicketNo = ticket;
   //Make sure the trade has appeared in the platform's history to avoid duplicate trades
   //My mod of Matt's code attempts to overcome the bastard crim's attempts to overcome Matt's code.
   bool TradeReturnedFromCriminal = false;
   if(!IsTesting())
   {
      while (!TradeReturnedFromCriminal)
      {
         TradeReturnedFromCriminal = O_R_CheckForHistory(ticket);
         if (!TradeReturnedFromCriminal)
         {
            Alert(Symbol(), " sent trade not in your trade history yet. Turn of this ea NOW.");
         }//if (!TradeReturnedFromCriminal)
      }//while (!TradeReturnedFromCriminal)
   }//if(!IsTesting)
   //Got this far, so trade send succeeded
   return(true);
   
}//End bool SendSingleTrade(int type, string comment, double lotsize, double price, double stop, double take)

//=============================================================================
//                           O_R_CheckForHistory()
//
//  This function is to work around a very annoying and dangerous bug in MT4:
//      immediately after you send a trade, the trade may NOT show up in the
//      order history, even though it exists according to ticket number.
//      As a result, EA's which count history to check for trade entries
//      may give many multiple entries, possibly blowing your account!
//
//  This function will take a ticket number and loop until
//  it is seen in the history.
//
//  RETURN VALUE:
//     TRUE if successful, FALSE otherwise
//
//
//  FEATURES:
//     * Re-trying under some error conditions, sleeping a random
//       time defined by an exponential probability distribution.
//
//     * Displays various error messages on the log for Debugging.
//
//  ORIGINAL AUTHOR AND DATE:
//     Matt Kennel, 2010
//
//=============================================================================
bool O_R_CheckForHistory(int ticket)
{
  string FunctionName = "O_R_CheckForHistory";
    int start = GetTickCount( );
  //My thanks to Matt for this code. He also has the undying gratitude of all users of my trading robots
   
   int lastTicket = OrderTicket();

   int cnt = 0;
   int err = GetLastError(); // so we clear the global variable.
   err = 0;
   bool exit_loop = false;
   bool success=false;

   while (!exit_loop) {
      /* loop through open trades */
      int total=OrdersTotal();
      for(int c = 0; c < total; c++) {
         if(OrderSelect(c,SELECT_BY_POS,MODE_TRADES) == true) {
            if (OrderTicket() == ticket) {
               success = true;
               exit_loop = true;
            }
         }
      }
      if (cnt > 3) {
         /* look through history too, as order may have opened and closed immediately */
         total=OrdersHistoryTotal();
         for(c = 0; c < total; c++) {
            if(OrderSelect(c,SELECT_BY_POS,MODE_HISTORY) == true) {
               if (OrderTicket() == ticket) {
                  success = true;
                  exit_loop = true;
               }
            }
         }
      }

      cnt = cnt+1;
      if (cnt > O_R_Setting_max_retries) {
         exit_loop = true;
      }
      if (!(success || exit_loop)) {
if(Error)Print("Did not find #"+ticket+" in history, sleeping, then doing retry #"+cnt);
         O_R_Sleep(O_R_Setting_sleep_time, O_R_Setting_sleep_max);
      }
   }
   // Select back the prior ticket num in case caller was using it.
   if (lastTicket >= 0) {
      OrderSelect(lastTicket, SELECT_BY_TICKET, MODE_TRADES);
   }
   if (!success) {
if(Debug)Print("Never found #"+ticket+" in history! crap!");
   }
   return(success);
}//End bool O_R_CheckForHistory(int ticket)

//=============================================================================
//                              O_R_Sleep()
//
//  This sleeps a random amount of time defined by an exponential
//  probability distribution. The mean time, in Seconds is given
//  in 'mean_time'.
//  This returns immediately if we are backtesting
//  and does not sleep.
//
//=============================================================================
void O_R_Sleep(double mean_time, double max_time)
{
  string FunctionName = "O_R_Sleep";
   int start = GetTickCount( );
   if (IsTesting()) {
      return;   // return immediately if backtesting.
   }

   double p = (MathRand()+1) / 32768.0;
   double t = -MathLog(p)*mean_time;
   t = MathMin(t,max_time);
   int ms = t*1000;
   if (ms < 10) {
      ms=10;
   }
   Sleep(ms);
}//End void O_R_Sleep(double mean_time, double max_time)

//+-------------------------------------------------------------------------------------------------------
void CountOpenTrades()
//+-------------------------------------------------------------------------------------------------------
{ 
   string FunctionName = "CountOpenTrades";
   int start = GetTickCount( );
   BuyOpen = false;
   SellOpen = false;   
   OpenTrades = 0;
   PendingTrades = 0;   
   BasketUpl = 0;
   OpenLots = 0;
   ArrayInitialize(TradeTicketNo, -1);
   BuyPending = false;
   SellPending = false;
   double target;
   Filled = 0;

   HedgingInProgress = false;
   static double HedgingProfit;
   if (OrdersTotal() == 0) return;

   int ot = OrdersTotal() - 1;
   
   for (int cc = 0; cc <= ot; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
     
      if (OrderMagicNumber() != MagicNumber) continue;
      if (OrderComment() == MagicNumber + "H")
      {
         HedgingInProgress = true;
         HedgingProfit =  OrderProfit() + OrderSwap() + OrderCommission();
         continue;
      }//if (OrderComment() == MagicNumber + "H")
                   
      if (OrderSymbol() == Symbol())
      {
         BasketUpl+= (OrderProfit() + OrderSwap() + OrderCommission());
         if (OrderType() == OP_BUYLIMIT  ) {BuyPending  = true; PendingTrades++; }
         if (OrderType() == OP_SELLLIMIT ) {SellPending = true; PendingTrades++; }
         if (OrderType() == OP_BUY )  {OpenLots+= OrderLots(); Filled++; BuyOpen  = true; TradeTicketNo[Filled] = OrderTicket();}
         if (OrderType() == OP_SELL)  {OpenLots+= OrderLots(); Filled++; SellOpen = true; TradeTicketNo[Filled] = OrderTicket();}
      }//if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
 
   }//for (int cc = OrdersTotal() - 1; cc <= 0; cc--)
   
   OpenTrades =  Filled;
   
	if(Debug)Print(FunctionName                         
	               ,C,"1, ID=",cc                       
	               ,C,"BasketUpl=",BasketUpl            
	               ,C,"typ=",OrderType()           
	               ,C,"Pending=",PendingTrades          
	               ,C,"Filled=",Filled                  
	               ,C,"OrderProfit()=",OrderProfit()    
	               ,C,"OrderSwap()=",OrderSwap()        
	               ,C,",Ticket[0]=",TradeTicketNo[0]  
	               ,C,",Ticket[1]=",TradeTicketNo[1]  
	               ,C,",Ticket[2]=",TradeTicketNo[2]  
	               ,C,",Ticket[3]=",TradeTicketNo[3]  
	               ,C,",Ticket[4]=",TradeTicketNo[4]
	               ,C,"Hedging=",  HedgingInProgress
	               ,C,"HedgingProfit=",HedgingProfit	               
	               );                                   
   
}//End void CountOpenTrades()

//+---------------------------------------------------------------------------------
void CloseAllTrades()
{
   string FunctionName = "CloseAllTrades";
   int start = GetTickCount( );
   
   ForceTradeClosure = false;
   
   if (OrdersTotal() == 0) return;
   
   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      if (OrderMagicNumber() != MagicNumber) continue;
      
//      if (OrderType() != OP_BUY && OrderType() != OP_SELL) continue;
      if (OrderSymbol() == Symbol() )
      {
         while(IsTradeContextBusy()) Sleep(100);
         bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 1000, Blue);
         if (result) cc++;
         if (!result) ForceTradeClosure = true;
      }//if (OrderSymbol() == Symbol() )
   
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
   
}//End void CloseAllTrades()

///////////////////////////////////////////////////////////////////////////////////////////////////////
//Balance/swap filters module
//+---------------------------------------------------------------------------------
void TradeDirectionBySwap()
{
   string FunctionName = "TradeDirectionBySwap";
   int start = GetTickCount( );

   //Sets TradeLong & TradeShort according to the positive/negative swap it attracts

   double LongSwap = MarketInfo(Symbol(), MODE_SWAPLONG);
   double ShortSwap = MarketInfo(Symbol(), MODE_SWAPSHORT);
   
   if (CadPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" || StringSubstr(Symbol(), 3, 3) == "CAD" || StringSubstr(Symbol(), 3, 3) == "cad" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "CAD" || StringSubstr(Symbol(), 0, 3) == "cad" )      
   }//if (CadPairsPositiveOnly)
   
   if (AudPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
   
   if (NzdPairsPositiveOnly)
   {
      if (StringSubstr(Symbol(), 0, 3) == "NZD" || StringSubstr(Symbol(), 0, 3) == "nzd" || StringSubstr(Symbol(), 3, 3) == "NZD" || StringSubstr(Symbol(), 3, 3) == "nzd" )      
      {
         if (LongSwap > 0) TradeLong = true;
         else TradeLong = false;
         if (ShortSwap > 0) TradeShort = true;
         else TradeShort = false;         
      }//if (StringSubstr(Symbol(), 0, 3) == "AUD" || StringSubstr(Symbol(), 0, 3) == "aud" || StringSubstr(Symbol(), 3, 3) == "AUD" || StringSubstr(Symbol(), 3, 3) == "aud" )      
   }//if (AudPairsPositiveOnly)
   
}//void TradeDirectionBySwap()

//+---------------------------------------------------------------------------------
bool IsThisPairTradable()
{
   string FunctionName = "IsThisPairTradable";
   int start = GetTickCount( );
   //Checks to see if either of the currencies in the pair is already being traded twice.
   //If not, then return true to show that the pair can be traded, else return false
   
   string c1 = StringSubstr(Symbol(), 0, 3);//First currency in the pair
   string c2 = StringSubstr(Symbol(), 3, 3);//Second currency in the pair
   int c1open = 0, c2open = 0;

   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
      /////////////////////////////////////////////////////////////////////////////////////////////////
      if (OrderSymbol() != Symbol() ) continue;
      /////////////////////////////////////////////////////////////////////////////////////////////////
      int index = StringFind(OrderSymbol(), c1);
      if (index > -1)
      {
         c1open++;         
      }//if (index > -1)
   
      index = StringFind(OrderSymbol(), c2);
      if (index > -1)
      {
         c2open++;         
      }//if (index > -1)
      if(Debug)Print("IsThisPairTradable2",",c1,",c1,",c2,",c2,",c1open,",c1open,",c2open,",c2open);   
      if (c1open == 2 || c2open == 2 )
      {
         //CanTradeThisPair = false;
         return(false);   
      }//if (c1open == 1 && c2open == 1)

   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so ok to trade
   return(true);
   
}//End bool IsThisPairTradable()

//+---------------------------------------------------------------------------------
bool BalancedPair(int type)
{

   string FunctionName = "BalancedPair";
   int start = GetTickCount( );
   //Only allow an individual currency to trade if it is a balanced trade
   //e.g. UJ Buy open, so only allow Sell xxxJPY.
   //The passed parameter is the proposed trade, so an existing one must balance that

   //This code courtesy of Zeljko (zkucera) who has my grateful appreciation.
   string BuyCcy1, SellCcy1, BuyCcy2, SellCcy2;

   if (type == OP_BUY)
   {
      BuyCcy1 = StringSubstr(Symbol(), 0, 3);
      SellCcy1 = StringSubstr(Symbol(), 3, 3);
   }//if (type == OP_BUY || type == OP_BUYSTOP)
   else
   {
      if (type == OP_SELL)
      {
         BuyCcy1 = StringSubstr(Symbol(), 3, 3);
         SellCcy1 = StringSubstr(Symbol(), 0, 3);
      }//if (type == OP_SELL)
   }//else   


   for (int cc = OrdersTotal() - 1; cc >= 0; cc--)
   {
      if (!OrderSelect(cc, SELECT_BY_POS)) continue;
      if (OrderSymbol() == Symbol()) continue;
      if (OrderMagicNumber() != MagicNumber) continue;      

      if (OrderType() == OP_BUY)
      {
         BuyCcy2 = StringSubstr(OrderSymbol(), 0, 3);
         SellCcy2 = StringSubstr(OrderSymbol(), 3, 3);
      }//if (OrderType() == OP_BUY || OrderType() == OP_BUYSTOP)
      else
      {
         if (OrderType() == OP_SELL)
         {
            BuyCcy2 = StringSubstr(OrderSymbol(), 3, 3);
            SellCcy2 = StringSubstr(OrderSymbol(), 0, 3);
         }//if (OrderType() == OP_SELL)
      }//else
      if (BuyCcy1 == BuyCcy2 || SellCcy1 == SellCcy2) return(false);
   }//for (int cc = OrdersTotal() - 1; cc >= 0; cc--)

   //Got this far, so it is ok to send the trade
   return(true);

}//End bool BalancedPair(int type)

//End Balance/swap filters module
///////////////////////////////////////////////////////////////////////////////////////////////////////

//+---------------------------------------------------------------------------------
bool ShouldWinningPositionClose()
{
   string FunctionName = "ShouldWinningPositionClose";
   int start = GetTickCount( );
   //Returns true if position should close, else returns false
   if(Debug)Print("Starting ShouldWinningPositionClose()");
   double target;
   RefreshRates();

   //Long trades. Closing at Bid captures the spread - result of research by Droland. Cheers Dave   
   for (int m=1;m<=4;m++)
   {
      if(Debug)Print ("dmml=",dmml,C,"TradeTicketNo[m]=",TradeTicketNo[m],",m=",m,",Target=",target,",Bid=",Bid);
      if (OrderSelect(TradeTicketNo[m], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)
      {
         target = OrderOpenPrice() + (  TargetAsPercentofOctave * dmml / 100);
         if(Debug)Print ("Band=",Band,",Target=",target,",Bid=",Bid,",dmml=",dmml,",OrderOpenPrice=",OrderOpenPrice());
         if (Bid >= target) return(true);
      }//if (OrderSelect(TradeTicketNo[1], SELECT_BY_TICKET) > -1 && OrderType() == OP_BUY && OrderProfit() > 0)  

   }//for (m=1;m<=4;m++)   

   //Short trades Closing at Ask captures the spread - result of research by Droland. Cheers Dave
   for (m=1;m<=4;m++)
   {
      if(Debug)Print ("TradeTicketNo[m]=",TradeTicketNo[m],",m=",m,",Target=",target,",Bid=",Bid);
      if (OrderSelect(TradeTicketNo[m], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
      {
         target = OrderOpenPrice() - (TargetAsPercentofOctave * dmml/100);
         if(Debug)Print ("Band=",Band,",Target=",target,",Bid=",Bid,",dmml=",dmml,",OrderOpenPrice=",OrderOpenPrice());
         if (Ask <= target) return(true);
      }//if (OrderSelect(TradeTicketNo[m], SELECT_BY_TICKET) > -1 && OrderType() == OP_SELL && OrderProfit() > 0)
   }//for (m=1;m<=4;m++)

   //Got this far, so position should remain open
   return(false);

}//End bool ShouldWinningPositionClose()

//+---------------------------------------------------------------------------------
bool HasMarketPassedExtreme()
{
   string FunctionName = "HasMarketPassedExtreme";
   int start = GetTickCount( );
   //Returns true if the basket has hit the outermost Death line.
   //Only called if CloseLosingBasket/UseHedging is chosen by the user

   RefreshRates();
   
   double target = uHedgeLine;
   if (Bid >= target) return(true);
   
   target = lHedgeLine;
   if (Bid <= target) return(true);

   return(false);
   
}//bool HasMarketPassedExtreme()

//+---------------------------------------------------------------------------------
void HedgePosition()
{
   string FunctionName = "HedgePosition";
   int start = GetTickCount( );
   //Called if a position needs hedging.
   
   double SendLots = OpenLots * HedgeLotMultiplier;
   int type;
   double price;
   TradeComment = MagicNumber + "_H";
   RefreshRates();
   if (BuyOpen) 
   {
      type = OP_SELL;
      price = Bid;
   }//if (BuyOpen) 
   
   if (SellOpen) 
   {
      type = OP_BUY;
      price = Ask;
   }//if (SellOpen) 
   
   bool result = SendSingleTrade(type, TradeComment, SendLots, price, 0, 0);

   if (result) HedgingInProgress = true;

   TradeComment = MagicNumber;
// Added to hide the hedge trade from possible other trades   
   MagicNumber++; 

   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);

}//End void HedgePosition()

//+---------------------------------------------------------------------------------
double gvg(string name)
{
   name = gvBase + name;
   return (GlobalVariableGet(name));
}//double gvg(string name)
//+---------------------------------------------------------------------------------
void gvs(string name, double value)
{
   name = gvBase + name;
   GlobalVariableSet(name, value);
}//void gvs(string name, double value)
//+---------------------------------------------------------------------------------
bool gvd(string name)
{
   name = gvBase + name;
   return (GlobalVariableDel(name));
}//bool gvd(string name)
//+---------------------------------------------------------------------------------
bool gvc(string name)
{
   name = gvBase + name;
   return (GlobalVariableCheck(name));
}//bool gvc(string name)

//+------------------------------------------------------------------+
void LookForFailedHedging()
{
   string FunctionName = "LookForFailedHedging";
   int start = GetTickCount( );
   //Close an open hedge trade if the market has moved back inside the hedge lines
   
   double high = NormalizeDouble(mml[12] + (dmml * MMLSToHedgeLine) , Digits);
   double low  = NormalizeDouble(mml[0]  - (dmml * MMLSToHedgeLine) , Digits);
   
   int cc;
   if (Ask < high && Bid > low)//Suggestion from DRoland
   {
         for (cc = OrdersTotal() - 1; cc >= 0; cc--)
         {
            if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
            if (OrderMagicNumber() != OrderMagicNumber() ) continue;
            if (OrderSymbol() != Symbol() ) continue;
            if (OrderComment() == MagicNumber + "_H")
            {
               while (IsTradeContextBusy() ) Sleep(100);
               bool result = OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 10000, Blue);
               if (!result) Alert("Order close fail");
               return;
            }//if (OrderComment() = MagicNumber + "_H") 
            
         }//for (cc = OrdersTotal() - 1; cc >= 0; cc--)         

      
   }//if (Bid < high && Bid > low)
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
  
}//void LookForFailedHedging()

//+------------------------------------------------------------------+
//| LookForPendingDeletion                                            |
//+------------------------------------------------------------------+
void LookForPendingDeletion()
{
  string FunctionName = "LookForPendingDeletion";
   int start = GetTickCount( );
   //Unfilled pandings can need deleting for a variety of reasons
   
   bool Delete = false;
   if(Debug)Print("BuyPending/SellPending=",BuyPending,",", SellPending);  

   //Balanced pairs
   if (UseZeljko)
   {
      if (BuyPending && !BalancedPair(OP_BUY) ) Delete = true;
      if (SellPending && !BalancedPair(OP_SELL) ) Delete = true;
      if(Debug)Print("delete2=",Delete);  
   }//if (UseZeljko)
   
   //Only trade a currency twice
   if (OnlyTradeCurrencyTwice && OpenTrades == 0)
   {
      if (!IsThisPairTradable() ) Delete = true;     
      if(Debug)Print("delete3=",Delete);  
   }//if (OnlyTradeCurrencyTwice)

   if (YesStop) Delete = true;
   if(Debug)Print("delete4=",Delete);  


   int ot = OrdersTotal() - 1;
   if (ot < 0) return;

   for (int cc = 0; cc <= ot; cc++)
   {
      if (!OrderSelect(cc, SELECT_BY_POS) ) continue;
     
      if (OrderMagicNumber() != MagicNumber) continue;
                 
      if (OrderSymbol() == Symbol())
      {
         int ticket = OrderTicket();
         if ((Bid  > OrderOpenPrice() + dmml && (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLSTOP)) || Delete==true ) 
         {
if(Debug)Print("in LookForPendingDeletion() OrderType() =",OrderType());
               OrderDelete(ticket);
               continue;
         }
         if (OrderType() == OP_SELLLIMIT || OrderType() == OP_BUYSTOP || Delete==true) 
         {
            if ((Bid  < OrderOpenPrice() - dmml && (OrderType() == OP_BUYSTOP || OrderType() == OP_SELLLIMIT)) || Delete==true ) 
            {
if(Debug)Print("in LookForPendingDeletion() OrderType() =",OrderType());
               OrderDelete(ticket);
               continue;
            }         
         }
      }//if (OrderSymbol() == Symbol())
 
   }//for (int cc = OrdersTotal() - 1; cc <= 0; cc--)
   
//   if (Delete) DeletePendingTrades();
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);

}//End void LookForPendingDeletion()

//+---------------------------------------------------------------------------------
void DeleteGlobals()
{
  string FunctionName = "DeleteGlobals";
   int start = GetTickCount( );

   gvd("mml0");
   gvd("mml1");
   gvd("mml2");
   gvd("mml3");
   gvd("mml4");
   gvd("mml5");
   gvd("mml6");
   gvd("mml7");
   gvd("mml8");
   gvd("mml9");
   gvd("mml10");
   gvd("mml11");
   gvd("mml12");
   gvd(upperhedgeline);
   gvd(lowerhedgeline);
      
    if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
}//void DeleteGlobals()

//+---------------------------------------------------------------------------------
void CreateGlobals()
{
   //only create if the mml0 gv does not already exist
   string FunctionName = "CreateGlobals";
   int start = GetTickCount( );
   if(Debug)Print(FunctionName,C, "gvc(mml0)=",gvc("mml0"),C,"GlobalVariableGet(gvBase + mml0)=", gvg( "mml0")); 
   if(!gvc("mml0") || gvc("mml0") == 0)
   {
      DrawLines();
      if(Debug)Print(FunctionName,C,"In the Loop");
      gvs("mml0", NormalizeDouble(mml[0],Digits));						if(Debug)Print("GV Check=",gvc("mml0"));         
      gvs("mml1", NormalizeDouble(mml[1],Digits));                if(Debug)Print("GV Check=",gvc("mml1"));         
      gvs("mml2", NormalizeDouble(mml[2],Digits));                if(Debug)Print("GV Check=",gvc("mml2"));         
      gvs("mml3", NormalizeDouble(mml[3],Digits));                if(Debug)Print("GV Check=",gvc("mml3"));         
      gvs("mml4", NormalizeDouble(mml[4],Digits));                if(Debug)Print("GV Check=",gvc("mml4"));         
      gvs("mml5", NormalizeDouble(mml[5],Digits));                if(Debug)Print("GV Check=",gvc("mml5"));         
      gvs("mml6", NormalizeDouble(mml[6],Digits));                if(Debug)Print("GV Check=",gvc("mml6"));         
      gvs("mml7", NormalizeDouble(mml[7],Digits));                if(Debug)Print("GV Check=",gvc("mml7"));         
      gvs("mml8", NormalizeDouble(mml[8],Digits));                if(Debug)Print("GV Check=",gvc("mml8"));         
      gvs("mml9", NormalizeDouble(mml[9],Digits));                if(Debug)Print("GV Check=",gvc("mml9"));         
      gvs("mml10", NormalizeDouble(mml[10],Digits));              if(Debug)Print("GV Check=",gvc("mml10"));        
      gvs("mml11", NormalizeDouble(mml[11],Digits));              if(Debug)Print("GV Check=",gvc("mml11"));        
      gvs("mml12", NormalizeDouble(mml[12],Digits));              if(Debug)Print("GV Check=",gvc("mml12"));        
      gvs(upperhedgeline, NormalizeDouble(uHedgeLine,Digits));    if(Debug)Print("GV Check=",gvc(upperhedgeline)); 
      gvs(lowerhedgeline, NormalizeDouble(lHedgeLine,Digits));    if(Debug)Print("GV Check=",gvc(lowerhedgeline)); 

   }  
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
}//void CreateGlobals()

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
   
   int start = GetTickCount( );

   
   // Load the stored MML's from globals after an EA reload
   // Only need to do this on first tick
   if (GetGVs)
   {
      GetLinesFromGV();
      GetGVs = false;
   }//if (GetGVs)

   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

   CountOpenTrades();
   if (OpenTrades == 0)
   {
      ForceTradeClosure = false;
      ForcePendingTradeDeletion = false;
      HedgingInProgress = false;
      DeleteGlobals();
      CalculateMMLs(false);      
      DrawLines();
   }//if (OpenTrades == 0)
   else
   {
      if (SaveLinesWhenTradesOpen)
      {
         CreateGlobals();
      }//if (SaveLinesWhenTradesOpen)
      else
      {
         DrawLines();
      }////else
   }//else
   
   //Deal with a trade closure failure
   if (ForceTradeClosure)
   {
      CloseAllTrades();
      return;
   }//if (ForceTradeClosure)

   if (ForcePendingTradeDeletion)
   {
      DeletePendingTrades();
      return;
   }//if (ForcePendingTradeDeletion)
   
   GetCurrentMMlPosition();
    
   /////////////////////////////////////////////////////////////////////////////////////////////////////////      
   //Position closure 
   if (OpenTrades > 0 && BasketUpl > 0)
   {
      if(Debug)Print("OpenTrades=",OpenTrades);
      double TPValue = 0;
      if (TakeProfitBasket) 
      {
         if (TakeProfitPercentage != 0 && TakeProfitDollar != 0) Alert("Both TakeProfitPercentage and TakeProfitDollar are set, I do not think you meant to do that??!!");
         if (TakeProfitPercentage == 0 && TakeProfitDollar == 0) Alert("TakeProfitBasket is true, but both TakeProfitPercentage and TakeProfitDollar are NOT set! One of these parameters needs to be greater than zero!");
         if (TakeProfitDollar > 0 ) TPValue=TakeProfitDollar;
         if (TakeProfitPercentage > 0) TPValue = AccountBalance()*(TakeProfitPercentage/100);    
      } // if (TakeProfiBasket)
      
      if (ShouldWinningPositionClose() || (TakeProfitBasket && BasketUpl >= TPValue) )
      {
         CloseAllTrades();
         
         return;
      }//if (ShouldWinningPositionClose() )      
   }//if (OPenTrades > 0 && OPenTrades < 4)
  
   if (OpenTrades > 0 && CloseLosingBasket)
   {
      if (HasMarketPassedExtreme() )
      {
         CloseAllTrades();
         return;
      }//if (HasMarketPassedExtreme() )   
   }//if (OpenTrades > 0 && CloseLosingBasket)

   //Successful hedging
   if (HedgingInProgress && BasketUpl > 0) 
   {
      CloseAllTrades();
      return;
   }//if (HedgingInProgress && BasketUpl > 0)
  
   //Failed hedging
   if (HedgingInProgress && BasketUpl < 0 && CloseHedgeOnReturnToGrid)
   {
      LookForFailedHedging();
   }//if (HedgingInProgres && BasketUpl < 0)
   
   //Delete pending trades for a variety of reasons
   LookForPendingDeletion();
   
  /////////////////////////////////////////////////////////////////////////////////////////////////////////      
  //Hedge losing trades once the market passes the extremes
   if (OpenTrades > 0 && UseHedging && !HedgingInProgress && BasketUpl < 0)
   {
      if (HasMarketPassedExtreme() )
      {
         HedgePosition();
      }//if (HasMarketPassedExtreme() )   
   }//if (OpenTrades > 0 && UseHedging && !HedgingInProgress && BasketUpl < 0)

   /////////////////////////////////////////////////////////////////////////////////////////////////////////////////   
   //Trading times
   YesStop = CheckTradeFilters();
if(Debug)Print("YesStop=" , YesStop);


   if(!YesStop)
   {
   //Available margin filters
      if (UseScoobsMarginCheck && OpenTrades > 0)
      {
         if(AccountMargin() > (AccountFreeMargin()/100)) 
         {
            Comment(gap + "There is insufficient margin to allow trading. You might want to turn off the UseScoobsMarginCheck input.");
            return;
         }//if(AccountMargin() > (AccountFreeMargin()/100)) 
      
      }//if (UseScoobsMarginCheck)

      if (UseForexKiwi && AccountMargin() > 0)
      {
         double ml = NormalizeDouble(AccountEquity() / AccountMargin() * 100, 2);
         if (ml < FkMinimumMarginPercent)
         {
            Comment("                                     There is insufficient margin percent to allow trading. " + DoubleToStr(ml, 2) + "%");
            return;
         }//if (ml < FkMinimumMarginPercent)
      
      }//if (UseForexKiwi && AccountMargin() > 0)

      //Swap filter
      TradeDirectionBySwap();

/*   //---- Once per bar stuff
   if(LastRunTime != iTime(NULL,0,0))
   {
      if(Debug)Print("dmml=",dmml,",MinBandSizeForTrading=",MinBandSizeForTrading);   


      LastRunTime = iTime(NULL,0,0);


   
   }//if(!IsBarClosed(0,true) ) 

*/   /////////////////////////////////////////////////////////////////////////////////////////////////////////
      if(Debug)Print( "Before LookForLimitOpportunities= "  );
 
      if(UseStopOrders && dmml > MinBandSizeForTrading)
      {
         if(Debug)Print("In LookForStopOpportunities");      
         int Trade = LookForStopOpportunities();
         if (MathAbs(Trade) == 1 && Send) SendTrade(type,price,lotsize,take, stop);
      }//if(!UseLimitOrders && dmml > MinBandSizeForTrading)   
   
      if (UseLimitOrders && dmml > MinBandSizeForTrading )
      {
         if(Debug)Print( "About to LookForLimitOpportunities= "  );
         Trade = LookForLimitOpportunities();
         if (MathAbs(Trade) == 1 && Send) 
         {
            SendTrade(type,price,lotsize,take, stop);
            if(Debug)Print("SendTrade,Band=",Band
                        ,C,"Lot=",lotsize
                        ,C,"Price=",price
                        ,C,"mml=",mml[Band]
                        ,C,"TradeTicketNo[1]=",TradeTicketNo[1]
                        ,C,"TradeTicketNo[2]=",TradeTicketNo[2]
                        ,C,"TradeTicketNo[3]=",TradeTicketNo[3]
                        ,C,"TradeTicketNo[4]=",TradeTicketNo[4]
                        );         
         }
      }
   }//if(!YesStop)
   
   DisplayUserFeedback();
   string FunctionName = "start"; 
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
}
//+------------------------------------------------------------------+
void DisplayUserFeedback()
{
   int start = GetTickCount();
   ScreenMessage = StringConcatenate(gap, TimeToStr(TimeLocal(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), NL,
                                     gap, "Band high: ", DoubleToStr(BandHigh, Digits), NL,
                                     gap, "Band low: ", DoubleToStr(BandLow, Digits), NL,
                                     gap, "Band no: ", Band, NL,
                                     gap, "MurreyMath Interval: ", DoubleToStr(dmml, Digits), NL,
                                     gap, "MinBandWidthForTrade: ",MinBandSizeForTrading, NL,
                                     gap, "Stoplevel: ", DoubleToStr(stoplevel, Digits), NL,
                                     gap, "Hedge=",TradeTicketNo[0],NL,                                     
                                     gap, "TicketNo[1]=",TradeTicketNo[1],NL,
                                     gap, "TicketNo[2]=",TradeTicketNo[2],NL,
                                     gap, "TicketNo[3]=",TradeTicketNo[3],NL,
                                     gap, "TicketNo[4]=",TradeTicketNo[4],NL,
                                     gap, "Basket Profit=",BasketUpl
                                     );   
                                    
   if (YesStop) ScreenMessage = StringConcatenate(ScreenMessage,NL,gap, "Outside trading hours. Trading STOPPED!!");
   
   Comment(ScreenMessage);
   string FunctionName = "DisplayUserFeedback";
   if(Timing)ShowTiming(start,GetTickCount(),FunctionName);
}

//+---------------------------------------------------------------------------------
void ShowTiming(int start, int end, string func)
{
    int time = end - start;
    if(Debug)Print("Timing " + func + " took:- " + time + " Milliseconds.");
}

//+---------------------------------------------------------------------------------
void CalculateMMLs(bool dohistory)
{
   datetime time1 = TimeLocal();
 	double bestFit;

   int pos = Bars -1;
   if ( NumBars > 0 && pos > NumBars )     pos = NumBars;
       
   if(!dohistory) pos=0;

   if( (nTime != Time[pos]) || (CurPeriod != Period()) ) 
   {
if(Debug)Print ("I(nTime != Time[pos]) || (CurPeriod != Period()),nTime=",nTime,",pos=",pos);

		while(pos>=0 )  
		{   	  
if(Debug)Print ("pos>=0,nTime=",nTime,",pos=",pos);
		   GetRange(pos);
   	
if(Debug)Print ("GetRangeCompleted----v1=",v1,",v2=",v2, ",0=",0, ",pos=",pos);
   	
   	   //determine fractal.....Really, once is enough for this. 
		   if(!fractalDone)   
		   {
		   	fractal = doFractal(v1,v2);
		   	fractalDone=true;
		   }//if(!fractalDone)   {
   	   
   	   double b1 = v1/MMmultiplier;
   	   double b2 = v2/MMmultiplier;
if(Debug)Print ("Funny b1 b2 bit,b1=",b1,",b2=",b2, ",mml[12]=",mml[12], ",mml[0]=",mml[0], ",pos=",pos);
   	   
			if( (b2> mml[12]|| b1< mml[0]) || UseOriginalCalcs || (b2-b1 < dmml * 2 )){ 
if(Debug)Print ("(b2> mml[12]|| b1< mml[0]) || UseOriginalCalcs || (b2-b1 < dmml * 2 ),b1=",b1,",b2=",b2,",pos=",pos);
				if(UseOriginalCalcs) 
				{
				   CalculateXY_old(pos);
				}
				else   
				{ 
				   CalculateXY(pos);  			
				   if (Redraw)    
				   {
				      RedrawDate = TimeToStr( Time[pos], TIME_DATE|TIME_MINUTES);
   	            DrawVlines(pos);
   	         }//if (Redraw)
   	      }//else
   	   }//if( (b2> mml[12]|| b1< mml[0])||(b2-b1 < dmml * 4 ) || UseOriginalCalcs )
   	   
   	   if (!UseOriginalCalcs)  DrawTlines(pos);      
		   nTime    = Time[pos];
		   CurPeriod= Period();
			pos--;
		}
		text = text + "Fractal=" + fractal + " Octave=" + octave;
	}
   datetime time2 = TimeLocal();
   int elapsed = time2 - time1;
if(Debug)Print( "Execution time " + TimeToStr(elapsed,TIME_MINUTES|TIME_SECONDS) + " seconds" );
	return(0);   
}

//+------------------------------------------------------------------+
void GetRange(int pos)  {
//+------------------------------------------------------------------+
   if (UseCloseForRangeCalcs && !UseOriginalCalcs ) {
      bn_Lo = iLowest(NULL,0,MODE_CLOSE,NewPeriod,pos);
      bn_Hi = iHighest(NULL,0,MODE_CLOSE,NewPeriod,pos);
if(Debug)Print ("GetRange--(UseCloseForRangeCalcs  )--bn_Lo=",bn_Lo,",bn_Hi=",bn_Hi, ",NewPeriod=",NewPeriod, ",pos=",pos);

      v1 = Close[bn_Lo]*MMmultiplier;
      v2 = Close[bn_Hi]*MMmultiplier;	   
if(Debug)Print ("GetRange--(UseCloseForRangeCalcs  )--bn_Lo=",bn_Lo,",bn_Hi=",bn_Hi, ",v1=",v1, ",v2=",v2, ",NewPeriod=",NewPeriod, ",pos=",pos);

   }
   else     
   {
      bn_Lo = iLowest(NULL,0,MODE_LOW,NewPeriod,pos);
      bn_Hi = iHighest(NULL,0,MODE_HIGH,NewPeriod,pos);
if(Debug)Print ("GetRange--(UseHiLoForRangeCalcs )--bn_Lo=",bn_Lo,",bn_Hi=",bn_Hi, ",NewPeriod=",NewPeriod, ",pos=",pos);

      v1 = Low[bn_Lo]*MMmultiplier;
      v2 = High[bn_Hi]*MMmultiplier;	   

if(Debug)Print ("GetRange--(UseHiLoForRangeCalcs )--bn_Lo=",bn_Lo,",bn_Hi=",bn_Hi, ",v1=",v1, ",v2=",v2,  ",NewPeriod=",NewPeriod, ",pos=",pos);
/*
      buff_str2 = UniqueID + " v1:" + "pos=" +pos;
      if(ObjectFind(buff_str2) == -1)       
      {
         ObjectCreate(buff_str2, OBJ_ARROW,0,Time[pos],v1/MMmultiplier);
         ObjectSet(buff_str2,OBJPROP_COLOR,White);
         ObjectSet(buff_str2,OBJPROP_ARROWCODE,158);
      }
      else
      {
         ObjectSet(buff_str2,OBJPROP_COLOR,White);
         ObjectSet(buff_str2,OBJPROP_ARROWCODE,158);
      }
      
      buff_str2 = UniqueID + " v2:" + "pos=" +pos;
      if(ObjectFind(buff_str2) == -1)       
      {
         ObjectCreate(buff_str2, OBJ_ARROW,0,Time[pos],v2/MMmultiplier);
         ObjectSet(buff_str2,OBJPROP_COLOR,White);
         ObjectSet(buff_str2,OBJPROP_ARROWCODE,158);
      }
      else
      {
         ObjectSet(buff_str2,OBJPROP_COLOR,White);
         ObjectSet(buff_str2,OBJPROP_ARROWCODE,158);
      }
*/      
   }   
}	   







//+------------------------------------------------------------------+   
void CalculateXY(int pos) {	
//+------------------------------------------------------------------+   
   range=(v2-v1);	
	sum=MathFloor(MathLog(fractal/range)/MathLog(2));	 

   DoBestFit();
   mmx = mx-mn;    

   if( (v1>=(3*mmx/16+mn)) && (v2<=(9*mmx/16+mn)) ) {x[1]=mn+mmx/2; } else x[1]=0;                                                        	
   if( (v1>=2*(mn-mmx/16))&& (v2<=(10*mmx/16+mn)) && (x[1]==0) ) {x[0]=mn+mmx/2;  } else x[0]=0;                                          
   if( (v1>=(mn+7*mmx/16))&& (v2<=(13*mmx/16+mn)) ) {x[3]=mn+3*mmx/4; }  else x[3]=0;                                                     	
   if( (v1>=(mn+6*mmx/16))&& (v2<=(18*mmx/16+mn))&& (x[3]==0) ) {x[4]=mx;   } else  x[4]=0;                                               	
   if( (v1>=2*(mn+mmx/16))&& (v2<=(14*mmx/16+mn)) && (x[0]==0) && (x[1]==0) && (x[3]==0) && (x[4]==0)) {x[2]=mn+3*mmx/4;  }  else x[2]=0; 	
   if( (x[0]+x[1]+x[2]+x[3]+x[4]) ==0 ) {x[5]=mx; }  else x[5]=0;                                                                         
	if( x[0]>0 ) {y[0]=mn;} else y[0]=0;                                                                                                   
	if( x[1]>0 )  {y[1]=mn+mmx/4;} else y[1]=0;                                                                                            
	if( x[2]>0 )  {y[2]=mn+mmx/4;} else y[2]=0;                                                                                            
	if( x[3]>0 )  {y[3]=mn+mmx/2;} else y[3]=0;                                                                                            
	if( x[4]>0 )   {y[4]=mn+mmx/2;} else y[4]=0;                                                                                           
	if( x[5]>0 )   {y[5]=mn; } else y[5]=0;                                                                                                
   
	      
   finalH = (x[0]+x[1]+x[2]+x[3]+x[4]+x[5]+x[6])/MMmultiplier;
   finalL = (y[0]+y[1]+y[2]+y[3]+y[4]+y[5]+y[6])/MMmultiplier;
		
   dmml = (finalH-finalL)/8;		   
   mml[0] =(finalL-dmml*2); 

   Redraw = false;

   if (mml[0] != lastMML || dmml != lastDmml || mml[12] != lastfinalH )   {
      Redraw = true;
   }
   
   for( i=1; i<OctLinesCnt; i++) {
      mml[i] = mml[i-1] + dmml;
   }//for( i=1; i<OctLinesCnt; i++) { 
   lastMML = mml[0];
   lastOctave = octave;
   lastfinalH = mml[12];
   lastDmml   = dmml;
   

	return(0);
}
//+------------------------------------------------------------------+
double doFractal(double v1, double v2)  {
//+------------------------------------------------------------------+   
   double fract;
            if( v2<=250000    && v2>25000    )     fract=100000;
   else     if( v2<=25000     && v2>2500     )     fract=10000;
   else     if( v2<=2500      && v2>250      )     fract=1000;
   else     if( v2<=250       && v2>25       )     fract=100;
   else     if( v2<=25        && v2>12.5     )     fract=12.5;
   else     if( v2<=12.5      && v2>6.25     )     fract=12.5;
   else     if( v2<=6.25      && v2>3.125    )     fract=6.25;
   else     if( v2<=3.125     && v2>1.5625   )     fract=3.125;
   else     if( v2<=1.5625    && v2>0.390625 )     fract=1.5625;
   else     if( v2<=0.390625  && v2>0        )     fract=0.1953125;
   return(fract);
}
//+------------------------------------------------------------------+
void  CreateAndSetVline(string objname, datetime date1, double price1,color pColor = 0,int pTimeframes=0, int pWidth = 0, int pBackground = 0, int pStyle = 0 )   {
//+------------------------------------------------------------------+
   ObjectCreate(objname,OBJ_VLINE,0,date1,0);
   ObjectSet(objname,OBJPROP_COLOR,pColor);
   ObjectSet(objname,OBJPROP_WIDTH,pWidth);
   ObjectSet(objname,OBJPROP_TIMEFRAMES,pTimeframes);  
   ObjectSet(objname,OBJPROP_BACK,pBackground); 
   ObjectSet(objname,OBJPROP_STYLE,pStyle);

}
//+------------------------------------------------------------------+
void  CreateAndSetTline(string objname, datetime date1, double price1,  datetime date2 , double price2,color pColor = 0,int pTimeframes=0, string pDescription="",int pWidth = 0, int pRay = 0, int pStyle = 0 )   {
//+------------------------------------------------------------------+
   ObjectCreate(objname,OBJ_TREND,0,date1,price1,date2,price2);
   ObjectSet(objname,OBJPROP_COLOR,pColor);
   ObjectSet(objname,OBJPROP_WIDTH,pWidth);
   ObjectSet(objname,OBJPROP_TIMEFRAMES,pTimeframes);  
   ObjectSet(objname,OBJPROP_RAY,pRay); 
   ObjectSet(objname,OBJPROP_STYLE,pStyle);             
   ObjectSetText(objname,pDescription);

}
//+------------------------------------------------------------------+
void DrawTlines( int pos)  {
//+------------------------------------------------------------------+   
   for( int i=0; i<OctLinesCnt; i++ ){
      buff_str  = UniqueID + i + "-" + TimeToStr( Time[pos], TIME_DATE|TIME_MINUTES);
      buff_str1 = UniqueID+""+ i + "-" + RedrawDate;   

      string buff_str3 = "v1/v2:" + DoubleToStr(v1,0)+","+DoubleToStr(v2,0)+
                         ",oct:" + DoubleToStr(octave,0)  +  
                         ",mn:" + DoubleToStr(mn,0) + 
                         ",mn+octave:" + DoubleToStr(mn+octave,0) + 
                         ",mx:" + DoubleToStr(mx,0);   
	    
      if(ObjectFind(buff_str1) == -1) {
         CreateAndSetTline( buff_str1, StrToTime(RedrawDate), mml[i],  Time[pos] , mml[i],clr[i],0, "",wdth[i], 0, 2 );	     
      }//if(ObjectFind(buff_str1) == -1) {
      else {
         ObjectSet(buff_str1, OBJPROP_TIME2, Time[pos]);
         if (i==12) ObjectSetText(buff_str1, buff_str3 );  
      }//else {
	     	         
      buff_str = UniqueID + "_txt " + i;
      if(ObjectFind(buff_str) == -1) {
         ObjectCreate(buff_str, OBJ_TEXT, 0, Time[0], shft);
         ObjectSetText(buff_str, ln_txt[i], 8, "Arial", clr[i]);
         ObjectMove(buff_str, 0, Time[0],  mml[i]+3*Point);
         
      } //if(ObjectFind(buff_str) == -1) { 
      else {
         ObjectMove(buff_str, 0, Time[0],  mml[i]+3*Point);
      }//else { 
	     
   } // for( int i=1; i<=OctLinesCnt; i++ )   
   
}
//+------------------------------------------------------------------+
void DrawVlines( int pos)  {
//+------------------------------------------------------------------+  
   buff_str2 = UniqueID + " Redraw:" + RedrawDate +"pos="+pos;
   CreateAndSetVline(buff_str2, Time[pos],mml[0], DimGray,0, 0, 1,  0 );

   lastMML = mml[0];
}
//+------------------------------------------------------------------+
void CalculateXY_old(int pos)     {
//+------------------------------------------------------------------+
   range=(v2-v1);	
	sum=MathFloor(MathLog(fractal/range)/MathLog(2));	 
   octave=fractal*(MathPow(0.5,sum));

	mn=MathFloor(v1/octave)*octave;


   if( (mn+octave)>v2 ) {
      mx=mn+octave; 
   }//if( (mn+octave)>v2 )
   else    {
      mx=mn+(2*octave);
   }//else  
   mmx = mx-mn;    

   if( (v1>=(3*mmx/16+mn))&& (v2<=(9*mmx/16+mn)))  {x[1]=mn+mmx/2; } else x[1]=0;                                                            //x[1]	
   if( (v1>=2*(mn-mmx/16))&& (v2<=(10*mmx/16+mn))  && (x[1]==0) ) {x[0]=mn+mmx/2;  } else x[0]=0;                                            //x[0]
   if( (v1>=(mn+7*mmx/16))&& (v2<=(13*mmx/16+mn))) {x[3]=mn+3*mmx/4; }  else x[3]=0;                                                         //x[3]	
   if( (v1>=(mn+6*mmx/16))&& (v2<=(18*mmx/16+mn))  && (x[3]==0) ) {x[4]=mx;   } else  x[4]=0;                                                //x[4]	
   if( (v1>=2*(mn+mmx/16))&& (v2<=(14*mmx/16+mn))  && (x[0]==0) && (x[1]==0) && (x[3]==0) && (x[4]==0)) {x[2]=mn+3*mmx/4;  }  else x[2]=0;   //x[2]	
   if( (x[0]+x[1]+x[2]+x[3]+x[4]) ==0 ) {x[5]=mx;} else x[5]=0;                                                                              //x[5]
	if( x[0]>0 ) {y[0]=mn;}       else y[0]=0;                                                                                                //y[0]                   	                     
	if( x[1]>0 ) {y[1]=mn+mmx/4;} else y[1]=0;                                                                                                //y[1]                     	                     
	if( x[2]>0 ) {y[2]=mn+mmx/4;} else y[2]=0;                                                                                                //y[2]                     	                     
	if( x[3]>0 ) {y[3]=mn+mmx/2;} else y[3]=0;                                                                                                //y[3]                      	                     
	if( x[4]>0 ) {y[4]=mn+mmx/2;} else y[4]=0;                                                                                                //y[4]                    	                     
	if( x[5]>0 ) {y[5]=mn; }      else y[5]=0;                                                                                                //y[5]
   
	      
   finalH = (x[0]+x[1]+x[2]+x[3]+x[4]+x[5])/MMmultiplier;
   finalL = (y[0]+y[1]+y[2]+y[3]+y[4]+y[5])/MMmultiplier;
		
   dmml = (finalH-finalL)/8;		   
   mml[0] =(finalL-dmml*2); //Set the bottom of the square (-2/8)
   for( i=1; i<OctLinesCnt; i++) {
      mml[i] = mml[i-1] + dmml;
   }//for( i=1; i<OctLinesCnt; i++) { 




   if (mml[0] != lastMML || dmml != lastDmml || mml[12] != lastfinalH )   {
      RedrawDate = TimeToStr( Time[pos], TIME_DATE|TIME_MINUTES);
      DrawVlines(pos);
   }
   lastMML = mml[0];
   lastOctave = octave;
   lastfinalH = mml[12];
   lastDmml   = dmml;
   DrawTlines( pos);
	return(0);
}
//+------------------------------------------------------------------+   
void DoBestFit()   {
//+------------------------------------------------------------------+   
	if (SetOctave > 0)   {
	   octave = SetOctave;
	}
	else    {
	   octave=fractal*(MathPow(0.5,sum));
      if(Debug)Print("Octave=",octave);
	}
	mn=MathFloor(v1/octave)*octave;
   if (SetOctave > 0)   {
   	for (int f = 1 ;f <= OctaveMultiplier;f++)    {
   	   if( (mn+octave*MathPow(2,f))> v2 ) {
   	      mx=mn+octave*MathPow(2,f);
   	      break; 
   	   }//if( (mn+octave)>v2 )
   	}//for (int f = 1 ;f <= OctaveMultiplier;f++) 
   }//if (SetOctave > 0)
   else  {
   	if( (mn+octave)>v2 ) {
   	   mx=mn+octave; 
   	}//if( (mn+octave)>v2 )
   	else    {
   	   mx=mn+(2*octave);
   	}//else  
   }// else
   return(0);   
}




